package tp.badugi.bot;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class BotPrudentCardExchangeStrategy extends BotCardInformationProvider{
	
	private final int noDoublesValueLimit = 7;
	
	public BotPrudentCardExchangeStrategy(){
		super();
	}
	
	public String[] exchangeCards(String[] cards){
		
		String[] cardsToExchange = {};
		
		String[][] colorDuplicate = this.getDuplicateColorCards(cards);
		String[][] valueDuplicate = this.getDuplicateValueCards(cards);
		
		List<Set<String>> intersection;
		List<Set<String>> difference;
		
		//no duplicates = exchange cards that have smaller value than the limit
		if (colorDuplicate[0].length == 0 && valueDuplicate[0].length == 0){
			
			cardsToExchange = this.noDoublesCardExchangeWithSetLimitStrategy(cards);
		}
		
		//only color duplicates
		else if (colorDuplicate[0].length > 0 && valueDuplicate[0].length == 0){
			//one pair, three or four. exchange amount of duplicates - 1 with worst values
			if(colorDuplicate.length == 1){
				
				cardsToExchange = new String[colorDuplicate[0].length - 1];				
				
				int[] duplicateValues = this.valuateEachCardInSet(colorDuplicate[0]);
				int[] sortedDuplicatedValues = duplicateValues.clone(); 
				
				Arrays.sort(sortedDuplicatedValues);
				
				for(int i = 0; i < sortedDuplicatedValues.length - 1; i++){
					for(int j = 0; j < duplicateValues.length; j++){
						if( sortedDuplicatedValues[i] == duplicateValues[j] ){
							cardsToExchange[i] = colorDuplicate[0][j];
						}
					}
				}
			}
			//two pairs; exchange each worst card from pair
			else if(colorDuplicate.length == 2){
				
				cardsToExchange = new String[colorDuplicate.length];
				
				cardsToExchange[0] = this.getCardWithMinimalValue(colorDuplicate[0]);
				cardsToExchange[1] = this.getCardWithMinimalValue(colorDuplicate[1]);
				
			}
			else{
				System.out.println("Impossible condition. colorDuplicate.length > 2");
			}
		}
		
		else if (colorDuplicate[0].length == 0 && valueDuplicate[0].length > 0){
			//one pair, three or four. exchange amount of duplicates - 1 whichever element
			if(valueDuplicate.length == 1){
				
				cardsToExchange = new String[valueDuplicate[0].length - 1];
				
				for(int i = 0; i < cardsToExchange.length; i++){
					cardsToExchange[i] = valueDuplicate[0][i];
				}
				
				
			}
			//two pairs; exchange wichever element from each pair
			else if(valueDuplicate.length == 2){
				
				cardsToExchange = new String[valueDuplicate.length];
				
				cardsToExchange[0] = valueDuplicate[0][0];
				
				cardsToExchange[1] = valueDuplicate[1][0];
				
			}
			else{
				System.out.println("Impossible condition. valueDuplicate.length > 2");
			}
		}
		
		else if (colorDuplicate[0].length > 0 && valueDuplicate[0].length > 0){
			
			intersection = new ArrayList<Set<String>>();
			difference = new ArrayList<Set<String>>();
			
			for(int i = 0; i < colorDuplicate.length; i++){
				for (int j = 0; j < valueDuplicate.length; j++){
					intersection.add(this.getIntersection(colorDuplicate[i], valueDuplicate[j]));
					difference.add(this.getDifference(colorDuplicate[i], valueDuplicate[j]));
				}
			}
			
			//no intersection set = value dup and color dup are separated;
			//exchange mininal from color dup and any from value dup
			if(intersection.get(0).size() == 0){
				
				cardsToExchange = new String[2];
				
				cardsToExchange[0] = valueDuplicate[0][0];
				
				cardsToExchange[1] = this.getCardWithMinimalValue(colorDuplicate[0]);
			}
			
			//1 intersection element = ths element has the same value and color as two ther elements
			//exchange this one card if MIN(e1,e2) from difference >= x, echenge two cards from difference otherwise
			//x == 7 in this case
			else if( intersection.get(0).size() == 1){
				
				String[] differenceCards = difference.get(0).toArray(new String[difference.get(0).size()]);
			
				String differenceCardWithMinimalValue = this.getCardWithMinimalValue(differenceCards);
				int differenceCardsMinimalValue = this.getCardValue(differenceCardWithMinimalValue);
				
				if( differenceCardsMinimalValue < 7){
					cardsToExchange = differenceCards.clone();					
				}
				else{
					String[] intersectionCards = intersection.get(0).toArray(new String[intersection.get(0).size()]);
					cardsToExchange = intersectionCards.clone();
				}
			}
			
			//if there are 2 pairs od the same colors or values that means we need to exchange 2 cards
			//exchange 2 cards from difference which have minimal sum from 2 difference pairs
			else if (colorDuplicate.length == 2 || valueDuplicate.length == 2){
				
				String[] firstDifferencePair = difference.get(0).toArray(new String[difference.get(0).size()]);
				String[] secondDifferencePair = difference.get(1).toArray(new String[difference.get(1).size()]);
				
				int firstDifferencePairSum = this.getCardSetValue(firstDifferencePair);
				int secondDifferencePairSum = this.getCardSetValue(secondDifferencePair);
				
				if( firstDifferencePairSum <= secondDifferencePairSum){
					cardsToExchange = firstDifferencePair;
				}
				else{
					cardsToExchange = secondDifferencePair;
				}
				
			}
			
			//there are 3 cards with the same color or value so we must exchange 3 cards
			//exchange cards with the worst sum from difference
			else if(colorDuplicate[0].length == 3 || valueDuplicate[0].length == 3){
				
				String[][] differencePairs = new String[difference.size()][3];
				int[] differencePairSums = new int[difference.size()];
				
				for(int i = 0; i < difference.size(); i++){
					differencePairs[i] = difference.get(i).toArray(new String[difference.get(i).size()]);
					differencePairSums[i] = this.getCardSetValue(differencePairs[i]);
				}
				
				if (differencePairSums.length == 1){
					cardsToExchange = differencePairs[0];
				}
				else{
					int[] sortedPairSums = differencePairSums;
					Arrays.sort(sortedPairSums);
					
					int minimalSum = sortedPairSums[0];
					
					for(int i = 0; i < differencePairSums.length; i++){
						if( differencePairSums[i] == minimalSum){
							cardsToExchange = differencePairs[i];
							break;
						}
					}
				}
				
			}
		}
		else{
			System.out.println("Card exchange impossible condition 5.");
		}
		
		return cardsToExchange;
	}
	
	private String[] noDoublesCardExchangeWithSetLimitStrategy(String[] cards){
		
		String[] cardsToExchange;
		
		int[] cardsValues = this.valuateEachCardInSet(cards);
		
		Set<String> cardsToExchangeSet = new TreeSet<String>();
		
		for(int i = 0; i < cards.length; i++){
			if( cardsValues[i] < this.noDoublesValueLimit){
				cardsToExchangeSet.add(cards[i]);
			}
		}		
		
		if(cardsToExchangeSet.isEmpty()){
			cardsToExchange = this.noDoublesGoodCardsNoAceOr2Strategy(cards);
		}
		else{
			cardsToExchange = cardsToExchangeSet.toArray(new String[cardsToExchangeSet.size()]);
		}
		
		return cardsToExchange;
	}
	
	private String[] noDoublesGoodCardsNoAceOr2Strategy(String[] cards){
		
		boolean aceOr2InCards = false;
		
		int i = 0;
		
		while(!aceOr2InCards && i < cards.length){
			if( cards[i].charAt(0) == 'A' || cards[i++].charAt(0) == '2' ){
				aceOr2InCards = true;
			}
		}
		
		if(!aceOr2InCards){
			return new String[]{ this.getCardWithMinimalValue(cards) };
		}
		
		return new String[]{};
	}
}
